package org.softmed.rest.generation;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.softmed.rest.config.Application;
import org.softmed.rest.generation.scafold.AppConfig;
import org.softmed.rest.generation.scafold.build.ApplicationProcessor;
import org.softmed.rest.generation.scafold.build.DirectoryReader;
import org.softmed.rest.generation.scafold.build.PersistenceProviderReader;
import org.softmed.rest.generation.solution.SolutionBuilder;

import com.google.inject.Inject;
import com.google.inject.name.Named;

public class ScafoldFacade {

	@Inject
	static DirectoryReader reader;

	@Inject
	@Named("ClassReader")
	static ApplicationProcessor classReader;

	@Inject
	@Named("ClassValidator")
	static ApplicationProcessor classValidator;

	@Inject
	@Named("GenericConfigReader")
	static ApplicationProcessor genericConfigReader;

	@Inject
	static PersistenceProviderReader persistenceProviderReader;

	@Inject
	@Named("PersistenceValidator")
	static ApplicationProcessor persistenceValidator;

	@Inject
	@Named("XMLSuiteReader")
	static ApplicationProcessor xmlSuiteReader;

	@Inject
	@Named("HandlerSuiteReader")
	static ApplicationProcessor handlerSuiteReader;

	@Inject
	@Named("ModuleBuilderReader")
	static ApplicationProcessor moduleBuilderReader;

	@Inject
	@Named("ApplicationConfigReader")
	static ApplicationProcessor applicationConfigReader;

	@Inject
	@Named("rootDir")
	static String rootDir;

	// @Inject
	// @Named("auto-gen-on-boot")
	// static boolean generateOnBoot;

	// static ClassDefinitionBuilder classDefinitionBuilder = new
	// ClassDefinitionBuilder();

	static List<AppConfig> previousApps;

	static List<AppConfig> apps;

	static Map<Long, AppConfig> appByIds = new HashMap<Long, AppConfig>();

	static Map<String, AppConfig> appByNames = new HashMap<String, AppConfig>();

	@Inject
	static SolutionBuilder solutionBuilder;

	public static void refresh(Map<Object, Object> options) throws Throwable {

		appByIds.clear();
		appByNames.clear();

		readData(options);
		if (solutionBuilder.persistenceProviderChanged(apps))
			readData(options);

		solutionBuilder.processAppConfigurations(apps);

		compile();

		previousApps = apps;
	}

	protected static void readData(Map<Object, Object> options)
			throws Throwable {
		Map<String, String> scafoldOptions = null;

		if (options != null) {
			scafoldOptions = (Map<String, String>) options.get("scafold");
		}

		// if (apps != null)
		// apps.clear();

		apps = null;

		apps = getApps();

		classReader.process(apps);
		classValidator.process(apps);
		// buildClassDefinitions(apps);

		genericConfigReader.process(apps);

		persistenceProviderReader.readPersistenceProviders(previousApps, apps,
				scafoldOptions);
		persistenceValidator.process(apps);

		xmlSuiteReader.process(apps);

		handlerSuiteReader.process(apps);

		moduleBuilderReader.process(apps);

		applicationConfigReader.process(apps);

	}

	private static void compile() {
		// appByIds.clear();
		// appByNames.clear();

		if (apps != null)
			for (AppConfig app : apps) {
				if (app.getId() != null)
					appByIds.put(app.getId(), app);

				appByNames.put(app.getName(), app);
			}

	}

	public static List<AppConfig> getApps() throws Throwable {
		List<AppConfig> apps = reader.getApps(rootDir);
		return apps;
	}

	public static Map<Long, AppConfig> getAppByIds() {
		return appByIds;
	}

	public static Map<String, AppConfig> getAppByNames() {
		return appByNames;
	}

	public static synchronized AppConfig getApp(Application app) {
		if (app.getId() != null)
			return appByIds.get(app.getId());

		return appByNames.get(app.getName());
	}

	public static DirectoryReader getReader() {
		return reader;
	}

	public static void setReader(DirectoryReader reader) {
		ScafoldFacade.reader = reader;
	}

	public static PersistenceProviderReader getPersistenceProviderReader() {
		return persistenceProviderReader;
	}

	public static void setPersistenceProviderReader(
			PersistenceProviderReader persistenceProviderReader) {
		ScafoldFacade.persistenceProviderReader = persistenceProviderReader;
	}

	public static String getRootDir() {
		return rootDir;
	}

	public static void setRootDir(String rootDir) {
		ScafoldFacade.rootDir = rootDir;
	}

	// public static boolean isGenerateOnBoot() {
	// return generateOnBoot;
	// }
	//
	// public static void setGenerateOnBoot(boolean generateOnBoot) {
	// ScafoldFacade.generateOnBoot = generateOnBoot;
	// }

	public static void setApps(List<AppConfig> apps) {
		ScafoldFacade.apps = apps;
	}

	public static void setAppByIds(Map<Long, AppConfig> appByIds) {
		ScafoldFacade.appByIds = appByIds;
	}

	public static void setAppByNames(Map<String, AppConfig> appByNames) {
		ScafoldFacade.appByNames = appByNames;
	}

	public static ApplicationProcessor getClassReader() {
		return classReader;
	}

	public static void setClassReader(ApplicationProcessor classReader) {
		ScafoldFacade.classReader = classReader;
	}

	public static ApplicationProcessor getClassValidator() {
		return classValidator;
	}

	public static void setClassValidator(ApplicationProcessor classValidator) {
		ScafoldFacade.classValidator = classValidator;
	}

	public static ApplicationProcessor getGenericConfigReader() {
		return genericConfigReader;
	}

	public static void setGenericConfigReader(
			ApplicationProcessor genericConfigReader) {
		ScafoldFacade.genericConfigReader = genericConfigReader;
	}

	public static ApplicationProcessor getPersistenceValidator() {
		return persistenceValidator;
	}

	public static void setPersistenceValidator(
			ApplicationProcessor persistenceValidator) {
		ScafoldFacade.persistenceValidator = persistenceValidator;
	}

	public static ApplicationProcessor getXmlSuiteReader() {
		return xmlSuiteReader;
	}

	public static void setXmlSuiteReader(ApplicationProcessor xmlSuiteReader) {
		ScafoldFacade.xmlSuiteReader = xmlSuiteReader;
	}

	public static ApplicationProcessor getHandlerSuiteReader() {
		return handlerSuiteReader;
	}

	public static void setHandlerSuiteReader(ApplicationProcessor handlerSuiteReader) {
		ScafoldFacade.handlerSuiteReader = handlerSuiteReader;
	}

	public static ApplicationProcessor getModuleBuilderReader() {
		return moduleBuilderReader;
	}

	public static void setModuleBuilderReader(
			ApplicationProcessor moduleBuilderReader) {
		ScafoldFacade.moduleBuilderReader = moduleBuilderReader;
	}

	public static ApplicationProcessor getApplicationConfigReader() {
		return applicationConfigReader;
	}

	public static void setApplicationConfigReader(
			ApplicationProcessor applicationConfigReader) {
		ScafoldFacade.applicationConfigReader = applicationConfigReader;
	}

	public static List<AppConfig> getPreviousApps() {
		return previousApps;
	}

	public static void setPreviousApps(List<AppConfig> previousApps) {
		ScafoldFacade.previousApps = previousApps;
	}

	public static SolutionBuilder getSolutionBuilder() {
		return solutionBuilder;
	}

	public static void setSolutionBuilder(SolutionBuilder solutionBuilder) {
		ScafoldFacade.solutionBuilder = solutionBuilder;
	}
	
	

}
